/**
 * 高速な文字列処理コードを生成します。
 *
 * Authors: Nazo
 * License: Public Domain
 */
module nazo.stringgen;

import std.string, nazo.sort;

/**
 * 複数検索のコードを生成します。
 * Bugs: コンパイル時に生成できない
 */
string genMultiFindCode(alias arr)(string[] strs){
  if(strs.length==0)return "return 0;";
  strs = sort(strs,delegate size_t(string t){return t.length;});
  string rv="{"\n;
  rv~="  int i"\n;
  if(strs.length==1 || strs[0].length!=strs[1].length){
    rv~="  for(i="~arr.stringof~".length-"~.toString(strs[0].length)~";i >"~(strs.length>1?" "~arr.stringof~".length-"~.toString(strs[1].length):"= 0")~";i--){"\n;
    if(strs[0].length==1)
      rv~="    if("~arr.stringof~"[i]=='"~strs[0][0]~"')"\n;
    else{
      if(strs[0].length==2)
        rv~="    if("~arr.stringof~"[i]=='"~strs[0][0]~"'&&"~arr.stringof~"[i+1]=='"~strs[0][1]~"')"\n;
      else
        rv~="    if("~arr.stringof~"[i]=='"~strs[0][0]~"'&&"~arr.stringof~"[i+1..i+"~.toString(strs[0].length)~"]==\""~strs[0][1..$]~"\")"\n;
    }
    rv~="      return true;"\n
        "  }"\n;
  }
  int m=2;
  for(;m<=strs.length;m++){
    while(m<strs.length && strs[m-1].length==strs[m].length)m++;
    rv~="  for(;i >"~(strs.length>m?" "~arr.stringof~".length - "~.toString(strs[m].length):"= 0")~";i--){"\n
        "    switch("~arr.stringof~"[i]){"\n;
    string[char] sarr;
    bool[char] sflag;
    foreach(n;0..m){
      if(strs[n].length==1){
        sarr[strs[n][0]]~="        return true;"\n;
        sflag[strs[n][0]] = true;
      }else{
        if(!(strs[n][0] in sflag)){
          if(strs[n].length==2)
            sarr[strs[n][0]]~="        if("~arr.stringof~"[i+1]=='"~strs[n][1]~"')"\n
                              "          return true;"\n;
          else
            sarr[strs[n][0]]~="        if("~arr.stringof~"[i+1..i+"~.toString(strs[n].length)~"]==\""~strs[n][1..$]~"\")"\n
                              "          return true;"\n;
        }
      }
    }
    foreach(k,v;sarr){
        rv~="      case '"~[k]~"':"\n ~ v;
        if(!(k in sflag))
          rv~="        break;"\n;
    }
    rv~="      default:"\n
        "    }"\n
        "  }"\n;
  }
  rv~="}";
  return rv;
}

import std.stdio;
unittest{
  string myarr="abcdefg";
/*  writefln(genMultiFindCode!(myarr)(["a"]));
  writefln(genMultiFindCode!(myarr)(["a","b"]));
  writefln(genMultiFindCode!(myarr)(["a","b","c"]));
  writefln(genMultiFindCode!(myarr)(["a","b","c","ad"]));
  writefln(genMultiFindCode!(myarr)(["ad","b","c","a"]));
  writefln(genMultiFindCode!(myarr)(["ad","addd"]));*/

/*  assert(mixin(genMultiFindCode!(myarr)(["a"]))==true);
  assert(mixin(genMultiFindCode!(myarr)(["ab"]))==true);
  assert(mixin(genMultiFindCode!(myarr)(["ac"]))==false);
  assert(mixin(genMultiFindCode!(myarr)(["a","b"]))==true);
  assert(mixin(genMultiFindCode!(myarr)(["ad","b"]))==true);*/
}


